"""
coding:utf-8
@software:PyCharm
@time:16:02
@Author:hoo
"""
import json
import re
import traceback
import requests
from commons.assert_util import assert_result
from commons.demo_util import demo
from commons.logger_util import logs, error_log
from commons.yaml_util import read_config_yaml, write_extract_yaml, read_extract_yaml
import jsonpath


class RequestsUtil:
    session = requests.session()

    def __init__(self, node, obj):
        self.base_url = read_config_yaml('base', node)
        self.obj = obj

    # 替换值的方法
    # Qa1(替换url,params,data,jsom,headers)
    # Qa2(string,int,float,list,dict)
    def replace_value(self, data):
        if data:
            # 保存数据类型
            data_type = type(data)
            # 判断数据类型
            if isinstance(data, dict) or isinstance(data, list):
                str_data = json.dumps(data)
            else:
                str_data = str(data)
            # 替换
            for cs in range(1, str_data.count('${') + 1):
                if "${" in str_data and "}" in str_data:
                    start_index = str_data.index("${")
                    end_index = str_data.index("}", start_index)
                    old_value = str_data[start_index:end_index + 1]
                    # 反射：通过字类的对象和方法符串调用方法
                    func_name = old_value[2:old_value.index('(')]
                    args_value1 = old_value[old_value.index('(') + 1:old_value.index(')')]
                    if args_value1 != "":
                        if "," in args_value1:
                            args_value2 = args_value1.split(',')
                            new_value = getattr(self.obj, func_name)(*args_value2)
                            print(new_value)
                        else:
                            print("func_name", func_name)
                            new_value = getattr(self.obj, func_name)(args_value1)
                    else:
                        new_value = getattr(self.obj, func_name)()
                    # 数字类型去掉“”
                    if isinstance(new_value, int) or isinstance(new_value, float):
                        str_data = str_data.replace('"' + old_value + '"', str(new_value))
                    else:
                        str_data = str_data.replace(old_value, str(new_value))
            # 还原数据类型
            if isinstance(data, dict) or isinstance(data, list):
                data = json.loads(str_data)
            else:
                data = data_type(str_data)
        return data

    # 统一请求封装
    def send_request(self, caseinfo):
        try:
            # 基础路径拼接
            name = caseinfo.pop("name")
            method = caseinfo['request'].pop("method")
            url0 = caseinfo['request'].pop("url")
            url = self.replace_value(url0)
            all_url = self.base_url + url
            # 请求头和参数替换
            for key, value in caseinfo['request'].items():
                if key in ['params', 'data', 'json', 'headers']:
                    caseinfo['request'][key] = self.replace_value(value)
                    # print(caseinfo['request'][key])
                elif key == "files":
                    for file_key, file_path in value.items():
                        value[file_key] = open(file_path, 'rb')
            # 输入信息日志
            logs("--------接口测试开始--------")
            logs("请求名称：%s" % name)
            logs("请求方式：%s" % method)
            logs("请求路径：%s" % all_url)
            if "headers" in caseinfo['request'].keys():
                logs("请求头：%s" % caseinfo['request']["headers"])
            if "params" in caseinfo['request'].keys():
                logs("请求params参数：%s" % caseinfo['request']["params"])
            elif "data" in caseinfo['request'].keys():
                logs("请求data参数：%s" % caseinfo['request']["data"])
            elif "json" in caseinfo['request'].keys():
                logs("请求json参数：%s" % caseinfo['request']["json"])
            if "files" in caseinfo['request'].keys():
                logs("请求files参数：%s" % caseinfo['request']["files"])
            res = RequestsUtil.session.request(method, all_url, **caseinfo['request'])
            # res_time = res.elapsed.total_seconds()
            result_text = res.text
            if "extract" in caseinfo.keys():
                for key, value in caseinfo["extract"].items():
                    if "(.*?)" in value or "(.+?)" in value:
                        zz_value = re.search(value, result_text)
                        if zz_value:
                            extract_value = {key: zz_value.group(1)}
                            write_extract_yaml(extract_value)
                    else:
                        try:
                            if type(res.json()) == dict:
                                resturn_json = res.json()
                            else:
                                resturn_json = eval(res.json())
                            js_value = jsonpath.jsonpath(resturn_json, value)
                            if js_value:
                                extract_value = {key: js_value[0]}
                                write_extract_yaml(extract_value)
                        except Exception as e:
                            print("extract返回的结果不是JSON格式,不能使用jsonpath提取")
            if type(res.json()) == dict:
                resdict = res.json()
            else:
                resdict = eval(res.json())
            assert_result(caseinfo['validate'], resdict, res.status_code)
            return res
        except Exception as e:
            error_log("发送请求send_request异常：%s" % str(traceback.format_exc()))

# if __name__ == '__main__':
#     data = "/cgi-bin/tags/create?access_token=${read_extract_yaml(access_token)}"
#     data2 = "{\"tag\": {\"name\":\"${read_extract_yaml(access_token)}\"}}"
#     print(RequestsUtil('base_wx_url', demo()).replace_value(data))
#     print(RequestsUtil('base_wx_url', demo()).replace_value(data2))
